Introduction
RNAseq data from:
Strenkert D, Schmollinger S, Gallaher SD, et al. Multiomics resolution of molecular events during a day in the life of Chlamydomonas. Proc Natl Acad Sci U S A. 2019;116(6):2374-2383.doi:10.1073/pnas.1815238116
Flow chart of my project RNAseq analysis part:
After treating the raw RNAseq data with my rna_workflow.smk, I obtained a counts table with each RNAseq library, following the time series order.
In this R markdown report, I perform a short analysis of this data and extract information on some potential or known Organellar Trans-Acting Factors (OTAFs) of Chlamydomonas reinhardtii.
## Loading counts data and metadata
meta_temp <- read.csv("../data/sample_DiscoRythm_format.tsv", sep="\t")
counts_rund_df <- read.csv("../results/mapping/full_data/total_counts_int.csv", sep="\t", row.names = 1)
## Picking colors for timepoints
meta_temp$color <- c(rep("#000f3b", 3), rep("#00144e", 3), rep("#001962", 3),
rep("#001162", 3), rep("#001789", 3), rep("#001eb1", 3),
rep("#143bff", 3), rep("#86bcf9", 3), rep("#ffc576", 3),
rep("#ffd400", 3), rep("#ffe900", 3), rep("#fff04e", 3),
rep("#fff589", 3), rep("#cec031", 3), rep("#ffbf00", 3),
rep("#001162", 3))
## Loading annotation data
annotations <- read.csv("../data/phytozome/Creinhardtii/v5.6/annotation/gene_annotation.tsv",
sep="\t")
annotations_organelles <- read.csv("../data/phytozome/Creinhardtii/v5.6/annotation/organelles_annotation.tsv",
sep="\t")
# /!\ Removing duplicated genes
annotations$gene_id <- make.unique(annotations$gene_id, sep=".")
## Matrix conversion
matrix_counts_DESeq2 <- as.matrix(counts_rund_df[,2:49])
rownames(matrix_counts_DESeq2) <- counts_rund_df[,1]
Hierarchical clustering of samples
dists <- dist(t(assay(rlog_data)))
par(mfrow=c(1,1))
tree_rlog <- hclust(dists)
my_colors = c("#ffc576", "#445cd7", "#fff04e", "#001789", "#faf5c6")
par(bg = "darkgrey", mfrow=c(1, 1))
plotColoredClusters(tree_rlog, labs = meta_temp$time,
ylab = NA, xlab = NA, cex = , las = 1,
cols = meta_temp$color, col = "white",
main = "Samples Euclidian distance hierarchical
clustering, rlog, complete linkage")
rect.hclust(tree_rlog, k=5, border=my_colors)
The hierarchical clustering of the transformed data gives coherent clusters, grouping samples according to time periods. In this report I decided to use these clusters to separate the samples in the differential expression analysis.
Differential expression analysis with DESeq2
Here I use the previously defined clusters as formula to look for differentially expressed genes with DESeq2. However this can also be achieved by using directly the time conditions (as the R script in the workflow does).
#### DESeq2 differential expression analysis by time point ####
ddsTimes <- DESeqDataSetFromMatrix(countData = matrix_counts_DESeq2,
colData = meta_temp,
design = ~ cluster) # ~ time_factor could be used instead
## Elimination of lowly expressed genes
ddsTimes <- ddsTimes[ rowSums(counts(ddsTimes)) > 60, ]
## Differential expression analysis
ddsTimes <- DESeq(ddsTimes)
time_points <- unique(meta_temp$cluster) # time_factor could be used instead
time_rep <- c(rep(time_points, c(1, rep(2, length(time_points)-1))), time_points[1])
pairs <- matrix(as.factor(time_rep), ncol = 2, byrow = TRUE)
# Significant genes initialisation
significant_genes <- c()
# Extraction of DESeq2 results
for (i in (1 : nrow(pairs))) {
ele <- pairs[i,]
text <- paste0(ele[1], "/", ele[2], " DEG:")
resDESeq <- results(ddsTimes, contrast = c("cluster", ele[1], ele[2]), # "time_factor" could be used instead
independentFiltering = TRUE, alpha=0.01)
message(text)
message( sum( resDESeq$padj < 0.01, na.rm=TRUE ) )
temp_list <- row.names(resDESeq[which(resDESeq$padj < 0.01),])
message(paste0(c(length(temp_list)/nrow(counts_rund_df) * 100), " %"))
significant_genes <- union(temp_list, significant_genes)
}
print(paste0("Total DEG in at least one time transition: ", (length(significant_genes)/nrow(counts_rund_df) * 100), " %"))
## [1] "Total DEG in at least one time transition: 85.614094148011 %"
The use of time condition (as in the workflow R script) instead of the clusters gives less DEG, about 70%.
Rhythm analysis with DiscoRhythm
DiscoRhythm:
Matthew Carlucci, Algimantas Kriščiūnas, Haohan Li, Povilas Gibas, Karolis Koncevičius, Art Petronis, Gabriel Oh, DiscoRhythm: an easy-to-use web application and R package for discovering rhythmicity, Bioinformatics, Volume 36, Issue 6, 15 March 2020, Pages 1952–1954, https://doi.org/10.1093/bioinformatics/btz834
## 0 2
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
## 4 6
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
## 8 10
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
## 10.5 11
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
## 11.5 12
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
## 14 16
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
## 18 20
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
## 22 24
## Total "3" "3"
## "Biological Sample 1 (1)" "Biological Sample 1 (1)"
## "Biological Sample 2 (1)" "Biological Sample 2 (1)"
## "Biological Sample 3 (1)" "Biological Sample 3 (1)"
# Our timepoints are not equidistant, we can use either the cosinor or Lomb-Scargle method to detect feature rhythms
# Cosinor
rythms_genes_CS <- discoODAs(input_data, period = 24, method = "CS",
circular_t = TRUE, ncores = 4)
# Lomb-Scargle
rythms_genes_LS <- discoODAs(input_data, period = 24, method = "LS",
circular_t = TRUE, ncores = 4)
par(mfrow=c(1,2))
hist(data.frame(rythms_genes_CS)$CS.qvalue, breaks = 100,
main = "qvalue cosinor",
xlab = "qvalue")
hist(data.frame(rythms_genes_LS)$LS.qvalue, breaks = 100,
main = "qvalue Lomb-Scargle",
xlab = "qvalue")

The Lomb-Scargle qvalue distribution has a problematic profile, we will focus on Cosinor.

The acrophase is the time when the expression of the gene peaks. We will focus on the acrophase parameter instead of the amplitude of the expression signal to find putative regulators. Indeed, what we are interested in is not the intensity of gene expression, but rather the timing of expression.
Annotation
## Extraction of annotations
row_CS <- row.names(CS_df)
CS_df$gene_id <- row_CS
CS_df <- left_join(CS_df, annotations)
id_organelle = annotations_organelles$gene_id
row.names(annotations_organelles) <- id_organelle
row_CS -> row.names(CS_df)
for (id in id_organelle) {
CS_df[id, "gene_symbol"] <- annotations_organelles[id,"gene_symbol"]
}
CS_df$gene_id <- row.names(CS_df)
CS_df$encoded <- "Nucleus"
CS_df[which(startsWith(CS_df$gene_id, "CreMt.")), "encoded"] <- "Mitochondrion"
CS_df[which(startsWith(CS_df$gene_id, "CreCp.")), "encoded"] <- "Chloroplast"
CS_df[which(startsWith(CS_df$gene_id, "CreMt.")), "subcellular_location"] <- "Mitochondrion"
CS_df[which(startsWith(CS_df$gene_id, "CreCp.")), "subcellular_location"] <- "Chloroplast"
CS_df[which(startsWith(CS_df$gene_id, "CreMt.")), "simplified_subcellular_location"] <- "Mitochondrion"
CS_df[which(startsWith(CS_df$gene_id, "CreCp.")), "simplified_subcellular_location"] <- "Chloroplast"
CS_df[which(startsWith(CS_df$gene_description, "OctotricoPeptide") == TRUE), ] -> CS_subset_opr
CS_df[which(startsWith(CS_df$gene_description, "PentatricoPeptide") == TRUE), ] -> CS_subset_ppr
# Genes both rhythmic and DE
final_data <- left_join(CS_df, sign_df, by = "gene_id")
final_data <- final_data[which(final_data$diff_expr == "yes"),]
final_data <- final_data[ which(!is.na(final_data$CS.acrophase)) , ]
General view of rhythmic genes acrophases
c(paste0("Chloroplast", " (", nrow(final_data[final_data$simplified_subcellular_location == "Chloroplast",]), ")"),
paste0("Chromosome", " (", nrow(final_data[final_data$simplified_subcellular_location == "Chromosome",]), ")"),
paste0("Cilium", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cilium",]), ")"),
paste0("Cytoplasm", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cytoplasm",]), ")"),
paste0("Cytoskeleton", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cytoskeleton",]), ")"),
paste0("Endoplasmic reticulum", " (", nrow(final_data[final_data$simplified_subcellular_location == "Endoplasmic reticulum",]), ")"),
paste0("Golgi apparatus", " (", nrow(final_data[final_data$simplified_subcellular_location == "Golgi apparatus",]), ")"),
paste0("Membrane", " (", nrow(final_data[final_data$simplified_subcellular_location == "Membrane",]), ")"),
paste0("Mitochondrion", " (", nrow(final_data[final_data$simplified_subcellular_location == "Mitochondrion",]), ")"),
paste0("Nucleus", " (", nrow(final_data[final_data$simplified_subcellular_location == "Nucleus",]), ")"),
paste0("Other", " (", nrow(final_data[final_data$simplified_subcellular_location == "Other",]), ")"),
paste0("unknown", " (", nrow(final_data[final_data$simplified_subcellular_location == "unknown",]), ")")) -> locations
#final_data2 <- filter(final_data, simplified_subcellular_location != "unknown")
ggplot(data = final_data, mapping = aes(x=CS.acrophase, fill=simplified_subcellular_location))+
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =0, ymax = Inf, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =0, ymax = Inf, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =0, ymax = Inf, alpha =0.3)+
geom_histogram(aes(x = CS.acrophase, y = ..density..), binwidth = 0.3) +
geom_line(stat = "density", alpha=0.5) +
facet_wrap(~simplified_subcellular_location)+
labs( x = "Acrophase", y = "Genes",
title ="Acrophases distribution according to cellular location",
subtitle = "Cosinor method")+
scale_fill_discrete(name = "Cellular location", labels = locations)
Putative and known regulators
# Recovering some rhythmic OTAFs
opr <- final_data[ which(startsWith(final_data$gene_description, "OctotricoPeptide Repeat")) , ]
ppr <- final_data[ which(startsWith(final_data$gene_description, "PentatricoPeptide Repeat")) , ]
tpr <- final_data[ which(startsWith(final_data$gene_description, "TetratricoPeptide Repeat")) , ]
otaf <- union_all(opr, ppr)
otaf <- union_all(otaf, tpr)
# Adding expression data:
columns <- colnames(otaf)
otaf <- left_join(otaf, rlog_df)
colnames(otaf) <- make.unique(c(columns, rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)))
# Predicted chloroplast imported OTAFs
multi_otaf_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Chloroplast"),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
multi_otaf_chloro <- rbind(multi_otaf_chloro, tmp_df)
}
multi_otaf_chloro <- multi_otaf_chloro[-1,]
# Predicted mitochondrion imported OTAFs
multi_otaf_mito <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Mitochondrion"),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
multi_otaf_mito <- rbind(multi_otaf_mito, tmp_df)
}
multi_otaf_mito <- multi_otaf_mito[-1,]
# Extracting organellar rhythmic genes
chloro <- final_data[ which(startsWith(final_data$gene_id, "CreCp")) , ]
mito <- final_data[ which(startsWith(final_data$gene_id, "CreMt")) , ]
# Adding expression data:
columns <- colnames(chloro)
chloro <- left_join(chloro, rlog_df)
colnames(chloro) <- make.unique(c(columns, rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)))
chloro$gene_symbol <- make.unique(chloro$gene_symbol)
columns <- colnames(mito)
mito <- left_join(mito, rlog_df)
colnames(mito) <- make.unique(c(columns, rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)))
# Chloroplast
multi_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in chloro$gene_symbol){
chloro[chloro$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
multi_chloro <- rbind(multi_chloro, tmp_df)
}
multi_chloro <- multi_chloro[-1,]
# Mitochondrion
multi_mito <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in mito$gene_symbol){
mito[mito$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
multi_mito <- rbind(multi_mito, tmp_df)
}
multi_mito <- multi_mito[-1,]
periode=24
ggplot(data = multi_otaf_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Rhythmic chloroplast localised OTAFs, expression models:",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 10))
ggplot(data = multi_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Rhythmic chloroplast genes, expression models:",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 10))
ggplot(data = multi_otaf_mito, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Rhythmic mitochondrion localised OTAFs, expression models:",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 10))
ggplot(data = multi_mito, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Rhythmic mitochondrion genes, expression models:",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 10))
To pair OTAFs and their putative organellar mRNA targets we must look at:
OTAFs and mRNA localised in the same organelle
With acrophases offset by a few hours. From mRNA the OTAF must be translated, then imported into the organelle where it might act on its mRNA target. Here I used a 4 hours shifted potential window.
acro_morning_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in chloro[which(chloro$CS.acrophase <16 & chloro$CS.acrophase >12 ),]$gene_symbol) {
chloro[chloro$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
acro_morning_chloro <- rbind(acro_morning_chloro, tmp_df)
}
acro_morning_chloro <- acro_morning_chloro[-1,]
otaf_chloro_acro_dawn <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <12 & otaf$CS.acrophase >8),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
otaf_chloro_acro_dawn <- rbind(otaf_chloro_acro_dawn, tmp_df)
}
otaf_chloro_acro_dawn <- otaf_chloro_acro_dawn[-1,]
# Plots
ggplot(data = otaf_chloro_acro_dawn, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 13, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 13, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 13, alpha =0.3)+
facet_wrap(~gene) +
ylim(4, 13) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast located OTAFs, acrophase at dawn",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
ggplot(data = acro_morning_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
ylim(10, 21) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =10, ymax = 21, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =10, ymax = 21, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =10, ymax = 21, alpha =0.3)+
facet_wrap(~gene) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast mRNA, acrophase in the morning",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
Here, we can identify known OTAF/chloroplast mRNA pairs/trios:
But also other potential OTAF/mRNA pairs!
acro_afternoon_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in chloro[which(chloro$CS.acrophase <20 & chloro$CS.acrophase >16 ),]$gene_symbol) {
chloro[chloro$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
acro_afternoon_chloro <- rbind(acro_afternoon_chloro, tmp_df)
}
acro_afternoon_chloro <- acro_afternoon_chloro[-1,]
otaf_chloro_acro_day <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <16 & otaf$CS.acrophase >12),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
otaf_chloro_acro_day <- rbind(otaf_chloro_acro_day, tmp_df)
}
otaf_chloro_acro_day <- otaf_chloro_acro_day[-1,]
# Plots
ggplot(data = otaf_chloro_acro_day, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 11, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 11, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 11, alpha =0.3)+
facet_wrap(~gene) +
ylim(4, 11) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast located OTAFs, acrophase at dawn",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
ggplot(data = acro_afternoon_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
ylim(12, 21) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =12, ymax = 21, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =12, ymax = 21, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =12, ymax = 21, alpha =0.3)+
facet_wrap(~gene) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast mRNA, acrophase at day",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
Here, we can identify known OTAF/chloroplast mRNA pairs:
MAC1 and psaC
MBB1 and psbB
MBC1 and psbC
TAA1 and psaA
TBC2 and psbC
TAB1 and psaB
And other potential OTAF/mRNA pairs…
acro_evening_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in chloro[which(chloro$CS.acrophase <24 & chloro$CS.acrophase >20 ),]$gene_symbol) {
chloro[chloro$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
acro_evening_chloro <- rbind(acro_evening_chloro, tmp_df)
}
acro_evening_chloro <- acro_evening_chloro[-1,]
otaf_chloro_acro_afternoon <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <20 & otaf$CS.acrophase >16),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
otaf_chloro_acro_afternoon <- rbind(otaf_chloro_acro_afternoon, tmp_df)
}
otaf_chloro_acro_afternoon <- otaf_chloro_acro_afternoon[-1,]
# Plots
ggplot(data = otaf_chloro_acro_afternoon, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 11, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 11, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 11, alpha =0.3)+
facet_wrap(~gene) +
ylim(4, 11) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast located OTAFs, acrophase at day",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
#ggplot(data = acro_evening_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
# ylim(12, 21) +
# annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =12, ymax = 21, alpha =0.3) +
# annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =12, ymax = 21, alpha =0.3) +
# annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =12, ymax = 21, alpha =0.3)+
# facet_wrap(~gene) +
# geom_smooth(method = "lm", se = FALSE, level = 0.95,
# formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
# fullrange = TRUE) +
# theme(legend.position = "none") +
# geom_point() +
# labs(y = "rlog(counts)", x = "Time (h)",
# title ="Chloroplast mRNA, acrophase in evening",
# subtitle = "Cosinor method")+
# theme(plot.title = element_text(size = 11))+
# theme(strip.text.x = element_text(size = 11))
print("No chloroplast gene with max expression at dusk.")
## [1] "No chloroplast gene with max expression at dusk."
acro_night_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in chloro[which(chloro$CS.acrophase <4 & chloro$CS.acrophase >0 ),]$gene_symbol) {
chloro[chloro$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
acro_night_chloro <- rbind(acro_night_chloro, tmp_df)
}
acro_night_chloro <- acro_night_chloro[-1,]
otaf_chloro_acro_dusk <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <24 & otaf$CS.acrophase >20),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
otaf_chloro_acro_dusk <- rbind(otaf_chloro_acro_dusk, tmp_df)
}
otaf_chloro_acro_dusk <- otaf_chloro_acro_dusk[-1,]
# Plots
ggplot(data = otaf_chloro_acro_dusk, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 8, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 8, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 8, alpha =0.3)+
facet_wrap(~gene) +
ylim(4, 8) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast located OTAFs, acrophase at dusk",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
ggplot(data = acro_night_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
ylim(11, 16) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =11, ymax = 16, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =11, ymax = 16, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =11, ymax = 16, alpha =0.3)+
facet_wrap(~gene) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast mRNA, acrophase in early night",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
acro_night_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in chloro[which(chloro$CS.acrophase <8 & chloro$CS.acrophase >4 ),]$gene_symbol) {
chloro[chloro$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
acro_night_chloro <- rbind(acro_night_chloro, tmp_df)
}
acro_night_chloro <- acro_night_chloro[-1,]
otaf_chloro_acro_night <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <4 & otaf$CS.acrophase >0),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
otaf_chloro_acro_night <- rbind(otaf_chloro_acro_night, tmp_df)
}
otaf_chloro_acro_night <- otaf_chloro_acro_night[-1,]
# Plots
ggplot(data = otaf_chloro_acro_night, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 9, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 9, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 9, alpha =0.3)+
facet_wrap(~gene) +
ylim(4, 9) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast located OTAFs, acrophase in early night",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
ggplot(data = acro_night_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
ylim(12, 16) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =12, ymax = 16, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =12, ymax = 16, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =12, ymax = 16, alpha =0.3)+
facet_wrap(~gene) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast mRNA, acrophase at night",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
acro_night_chloro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in chloro[which(chloro$CS.acrophase <12 & chloro$CS.acrophase >8 ),]$gene_symbol) {
chloro[chloro$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
acro_night_chloro <- rbind(acro_night_chloro, tmp_df)
}
acro_night_chloro <- acro_night_chloro[-1,]
otaf_chloro_acro_night <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <8 & otaf$CS.acrophase >4),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
otaf_chloro_acro_night <- rbind(otaf_chloro_acro_night, tmp_df)
}
otaf_chloro_acro_night <- otaf_chloro_acro_night[-1,]
# Plots
ggplot(data = otaf_chloro_acro_night, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 13, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 13, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 13, alpha =0.3)+
facet_wrap(~gene) +
ylim(4, 13) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast located OTAFs, acrophase at end of night",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
ggplot(data = acro_night_chloro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
ylim(12, 21) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =12, ymax = 21, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =12, ymax = 21, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =12, ymax = 21, alpha =0.3)+
facet_wrap(~gene) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Chloroplast mRNA, acrophase at dawn",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
Here, we can identify a known OTAF/chloroplast mRNA pair: MRL1 and rbcL
And other potential OTAF/mRNA pairs…?
acro_mito <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in mito$gene_symbol) {
mito[mito$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
acro_mito <- rbind(acro_mito, tmp_df)
}
acro_mito <- acro_mito[-1,]
otaf_mito_acro <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf[which(otaf$subcellular_location == "Mitochondrion"),]$gene_symbol){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
otaf_mito_acro <- rbind(otaf_mito_acro, tmp_df)
}
otaf_mito_acro <- otaf_mito_acro[-1,]
# Plots
ggplot(data = otaf_mito_acro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 13, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 13, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 13, alpha =0.3)+
facet_wrap(~gene) +
ylim(4, 13) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Mitochondrion located OTAFs,",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
ggplot(data = acro_mito, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
ylim(11, 16) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =11, ymax = 16, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =11, ymax = 16, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =11, ymax = 16, alpha =0.3)+
facet_wrap(~gene) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="Mitochondrion mRNA",
subtitle = "Cosinor method")+
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
ncl_df <- data.frame(time=0, gene_expression=0.0, gene="")
for (prot in otaf$gene_symbol){
if (startsWith(prot, "NCL") | startsWith(prot, "NCC") ){
otaf[otaf$gene_symbol == prot, 19:66] %>%
pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
tmp_df$gene <- prot
ncl_df <- rbind(ncl_df, tmp_df)
}
}
ncl_df <- ncl_df[-1,]
# Plots
ggplot(data = ncl_df, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) +
annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =3, ymax = 9, alpha =0.3) +
annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =3, ymax = 9, alpha =0.3) +
annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =3, ymax = 9, alpha =0.3)+
facet_wrap(~gene) +
ylim(3, 9) +
geom_smooth(method = "lm", se = FALSE, level = 0.95,
formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
fullrange = TRUE) +
theme(legend.position = "none") +
geom_point() +
labs(y = "rlog(counts)", x = "Time (h)",
title ="All rhythmic NCL expression",
subtitle = "Cosinor method") +
theme(plot.title = element_text(size = 11))+
theme(strip.text.x = element_text(size = 11))
References
Eberhard S, Loiselay C, Drapier D, Bujaldon S, Girard-Bascou J, Kuras R, Choquet Y, Wollman FA. Dual functions of the nucleus-encoded factor TDA1 in trapping and translation activation of atpA transcripts in Chlamydomonas reinhardtii chloroplasts. Plant J. 2011 Sep;67(6):1055-66. doi: 10.1111/j.1365-313X.2011.04657.x. Epub 2011 Jul 18. PMID: 21623973.
Wang F, Johnson X, Cavaiuolo M, Bohne AV, Nickelsen J, Vallon O. Two Chlamydomonas OPR proteins stabilize chloroplast mRNAs encoding small subunits of photosystem II and cytochrome b6 f. Plant J. 2015 Jun;82(5):861-73. doi: 10.1111/tpj.12858. PMID: 25898982.
Cline, S. G., Laughbaum, I. A. and Hamel, P. P. (2017) CCS2, an Octatricopeptide-Repeat Protein, Is Required for Plastid Cytochrome c Assembly in the Green Alga Chlamydomonas reinhardtii. Frontiers in plant science, 8, 1306. https://doi.org/10.3389/fpls.2017.01306
Viola S, Cavaiuolo M, Drapier D, et al. MDA1, a nucleus-encoded factor involved in the stabilization and processing of the atpA transcript in the chloroplast of Chlamydomonas. The Plant Journal: for Cell and Molecular Biology. 2019 Jun;98(6):1033-1047. DOI: 10.1111/tpj.14300.
Shin-Ichiro Ozawa, Marina Cavaiuolo, Domitille Jarrige, Richard Kuras, Mark Rutgers, Stephan Eberhard, Dominique Drapier, Francis-André Wollman, Yves Choquet, The OPR Protein MTHI1 Controls the Expression of Two Different Subunits of ATP Synthase CFo in Chlamydomonas reinhardtii, The Plant Cell, Volume 32, Issue 4, April 2020, Pages 1179–1203, https://doi.org/10.1105/tpc.19.00770
## R version 4.0.3 (2020-10-10)
## Platform: x86_64-conda-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
##
## Matrix products: default
## BLAS/LAPACK: /shared/ifbstor1/software/miniconda/envs/r-4.0.3/lib/libopenblasp-r0.3.10.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] parallel stats4 stats graphics grDevices utils datasets
## [8] methods base
##
## other attached packages:
## [1] gprofiler2_0.2.1 DiscoRhythm_1.6.0
## [3] pheatmap_1.0.12 ClassDiscovery_3.4.0
## [5] oompaBase_3.2.9 cluster_2.1.1
## [7] DESeq2_1.30.1 SummarizedExperiment_1.20.0
## [9] Biobase_2.50.0 GenomicRanges_1.42.0
## [11] GenomeInfoDb_1.26.7 IRanges_2.24.1
## [13] S4Vectors_0.28.1 BiocGenerics_0.36.1
## [15] MatrixGenerics_1.2.1 matrixStats_0.60.1
## [17] data.table_1.14.0 forcats_0.5.1
## [19] stringr_1.4.0 dplyr_1.0.7
## [21] purrr_0.3.4 readr_2.0.1
## [23] tidyr_1.1.3 tibble_3.1.4
## [25] tidyverse_1.3.1 knitr_1.33
## [27] factoextra_1.0.7 ggplot2_3.3.5
## [29] FactoMineR_2.4
##
## loaded via a namespace (and not attached):
## [1] utf8_1.2.2 shinydashboard_0.7.1 tidyselect_1.1.1
## [4] heatmaply_1.2.1 RSQLite_2.2.8 AnnotationDbi_1.52.0
## [7] htmlwidgets_1.5.4 grid_4.0.3 TSP_1.1-10
## [10] BiocParallel_1.24.1 munsell_0.5.0 codetools_0.2-18
## [13] DT_0.18 miniUI_0.1.1.1 withr_2.4.2
## [16] colorspace_2.0-2 highr_0.9 gnm_1.1-1
## [19] rstudioapi_0.13 leaps_3.1 oompaData_3.1.1
## [22] ggsignif_0.6.2 labeling_0.4.2 GenomeInfoDbData_1.2.4
## [25] farver_2.1.0 bit64_4.0.5 vctrs_0.3.8
## [28] generics_0.1.0 lambda.r_1.2.4 xfun_0.25
## [31] R6_2.5.1 seriation_1.3.0 locfit_1.5-9.4
## [34] bitops_1.0-7 cachem_1.0.6 DelayedArray_0.16.3
## [37] assertthat_0.2.1 promises_1.2.0.1 shinycssloaders_1.0.0
## [40] scales_1.1.1 nnet_7.3-15 ggExtra_0.9
## [43] gtable_0.3.0 MetaCycle_1.2.0 rlang_0.4.11
## [46] genefilter_1.72.1 systemfonts_1.0.2 scatterplot3d_0.3-41
## [49] splines_4.0.3 rstatix_0.7.0 lazyeval_0.2.2
## [52] shinyBS_0.61 broom_0.7.9 abind_1.4-5
## [55] BiocManager_1.30.16 yaml_2.2.1 reshape2_1.4.4
## [58] modelr_0.1.8 backports_1.2.1 httpuv_1.6.2
## [61] tools_4.0.3 ellipsis_0.3.2 kableExtra_1.3.4
## [64] jquerylib_0.1.4 RColorBrewer_1.1-2 Rcpp_1.0.7
## [67] plyr_1.8.6 zlibbioc_1.36.0 RCurl_1.98-1.4
## [70] ggpubr_0.4.0 viridis_0.6.1 haven_2.4.3
## [73] ggrepel_0.9.1 fs_1.5.0 magrittr_2.0.1
## [76] futile.options_1.0.1 magick_2.7.2 openxlsx_4.2.4
## [79] reprex_2.0.1 hms_1.1.0 shinyjs_2.0.0
## [82] mime_0.11 evaluate_0.14 xtable_1.8-4
## [85] XML_3.99-0.7 VennDiagram_1.6.20 rio_0.5.27
## [88] mclust_5.4.7 readxl_1.3.1 gridExtra_2.3
## [91] compiler_4.0.3 crayon_1.4.1 htmltools_0.5.2
## [94] mgcv_1.8-34 later_1.3.0 tzdb_0.1.2
## [97] geneplotter_1.68.0 lubridate_1.7.10 DBI_1.1.1
## [100] formatR_1.11 dbplyr_2.1.1 MASS_7.3-53.1
## [103] relimp_1.0-5 BiocStyle_2.18.1 Matrix_1.3-4
## [106] car_3.0-11 cli_3.0.1 pkgconfig_2.0.3
## [109] flashClust_1.01-2 registry_0.5-1 foreign_0.8-81
## [112] plotly_4.9.4.1 xml2_1.3.2 foreach_1.5.1
## [115] svglite_2.0.0 annotate_1.68.0 bslib_0.2.5.1
## [118] webshot_0.5.2 XVector_0.30.0 rvest_1.0.1
## [121] digest_0.6.27 rmarkdown_2.10 cellranger_1.1.0
## [124] dendextend_1.15.1 curl_4.3.2 shiny_1.6.0
## [127] nlme_3.1-152 lifecycle_1.0.0 jsonlite_1.7.2
## [130] carData_3.0-4 futile.logger_1.4.3 qvcalc_1.0.2
## [133] viridisLite_0.4.0 fansi_0.5.0 pillar_1.6.2
## [136] lattice_0.20-41 fastmap_1.1.0 httr_1.4.2
## [139] survival_3.2-10 glue_1.4.2 zip_2.2.0
## [142] UpSetR_1.4.0 iterators_1.0.13 bit_4.0.4
## [145] stringi_1.7.3 sass_0.4.0 blob_1.2.2
## [148] memoise_2.0.0
LS0tCnRpdGxlOiAicmh5dGhtaWNfYW5hbHlzZXMuUm1kIgphdXRob3I6ICJEb21pdGlsbGUgSmFycmlnZSIKZGF0ZTogJ2ByIFN5cy5EYXRlKClgJwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgdGhlbWU6IHlldGkKICAgIHRvYzogeWVzCiAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIgogIHBkZl9kb2N1bWVudDoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPVRSVUV9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGV2YWwgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUpCgpvcHRpb25zKHNjaXBlbiA9IDEyKSAjIyBNYXggbnVtYmVyIG9mIGRpZ2l0cyBmb3Igbm9uLXNjaWVudGlmaWMgbm90YXRpb24KYGBgCgpgYGB7ciB3b3JraW5nX2RpciwgaW5jbHVkZT1GQUxTRX0Kc2V0d2QoIi9zaGFyZWQvaWZic3RvcjEvcHJvamVjdHMvZHViaWkyMDIxL2RqYXJyaWdlL3Byb2pldF9zY2llbnRpZmlxdWUvc2NyaXB0cyIpCmBgYAoKYGBge3IgbGlicmFyaWVzLCBpbmNsdWRlPUZBTFNFfQpyZXF1aXJlZF9saWIgPC0gYygiRmFjdG9NaW5lUiIsCiAgICAgICAgICAgICAgICAgICJmYWN0b2V4dHJhIiwKICAgICAgICAgICAgICAgICAgImtuaXRyIiwKICAgICAgICAgICAgICAgICAgInRpZHl2ZXJzZSIsCiAgICAgICAgICAgICAgICAgICJkYXRhLnRhYmxlIiwKICAgICAgICAgICAgICAgICAgIlN1bW1hcml6ZWRFeHBlcmltZW50IiwKICAgICAgICAgICAgICAgICAgInRpYmJsZSIsCiAgICAgICAgICAgICAgICAgICJERVNlcTIiLAogICAgICAgICAgICAgICAgICAiZHBseXIiLAogICAgICAgICAgICAgICAgICAiQ2xhc3NEaXNjb3ZlcnkiLAogICAgICAgICAgICAgICAgICAicGhlYXRtYXAiKQoKcmVxdWlyZWRfYmlvYyA8LSBjKCJEaXNjb1JoeXRobSIsCiAgICAgICAgICAgICAgICAgICAiZ3Byb2ZpbGVyMiIpCgojIyMgQ1JBTiBsaWJyYXJpZXMgCmZvciAobGliIGluIHJlcXVpcmVkX2xpYikgewogICAgaWYgKCFyZXF1aXJlKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgewogICAgICAgIGluc3RhbGwucGFja2FnZXMobGliKQogICAgfQogICAgcmVxdWlyZShsaWIsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKfQoKCiMjIyBCaW9jbWFuYWdlciBsaWJyYXJpZXMgCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseT1UUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKCmZvciAobGliIGluIHJlcXVpcmVkX2Jpb2MpewogICAgaWYgKCFyZXF1aXJlKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgewogICAgICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQogICAgfQogICAgcmVxdWlyZShsaWIsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKfQoKCmBgYAoKIyMgSW50cm9kdWN0aW9uCgojIyMjIFJOQXNlcSBkYXRhIGZyb206CgoqKlN0cmVua2VydCBELCBTY2htb2xsaW5nZXIgUywgR2FsbGFoZXIgU0QsIGV0IGFsLiBNdWx0aW9taWNzIHJlc29sdXRpb24gb2YgbW9sZWN1bGFyIGV2ZW50cyBkdXJpbmcgYSBkYXkgaW4gdGhlIGxpZmUgb2YgQ2hsYW15ZG9tb25hcy4gUHJvYyBOYXRsIEFjYWQgU2NpIFUgUyBBLiAyMDE5OzExNig2KToyMzc0LTIzODMuW2RvaToxMC4xMDczL3BuYXMuMTgxNTIzODExNl0oaHR0cHM6Ly93d3cucG5hcy5vcmcvY29udGVudC8xMTYvNi8yMzc0KSoqCgoKIyMjIyBGbG93IGNoYXJ0IG9mIG15IHByb2plY3QgUk5Bc2VxIGFuYWx5c2lzIHBhcnQ6CiFbbXkgUk5Bc2VxIHdvcmtmbG93XShmbG93X2NoYXJ0X1JOQV9naXRodWJfdmVyLnBuZykKCgpBZnRlciB0cmVhdGluZyB0aGUgcmF3IFJOQXNlcSBkYXRhIHdpdGggbXkgYHJuYV93b3JrZmxvdy5zbWtgLCBJIG9idGFpbmVkIGEgY291bnRzIHRhYmxlIHdpdGggZWFjaCBSTkFzZXEgbGlicmFyeSwgZm9sbG93aW5nIHRoZSB0aW1lIHNlcmllcyBvcmRlci4KCkluIHRoaXMgUiBtYXJrZG93biByZXBvcnQsIEkgIHBlcmZvcm0gYSBzaG9ydCBhbmFseXNpcyBvZiB0aGlzIGRhdGEgYW5kIGV4dHJhY3QgaW5mb3JtYXRpb24gb24gc29tZSBwb3RlbnRpYWwgb3Iga25vd24gT3JnYW5lbGxhciBUcmFucy1BY3RpbmcgRmFjdG9ycyAoT1RBRnMpIG9mIF9DaGxhbXlkb21vbmFzIHJlaW5oYXJkdGlpXy4KCmBgYHtyIGRhdGFfbG9hZGluZ19hbmRfcHJlcGFyYXRpb259CgojIyBMb2FkaW5nIGNvdW50cyBkYXRhIGFuZCBtZXRhZGF0YQptZXRhX3RlbXAgPC0gcmVhZC5jc3YoIi4uL2RhdGEvc2FtcGxlX0Rpc2NvUnl0aG1fZm9ybWF0LnRzdiIsIHNlcD0iXHQiKQpjb3VudHNfcnVuZF9kZiA8LSByZWFkLmNzdigiLi4vcmVzdWx0cy9tYXBwaW5nL2Z1bGxfZGF0YS90b3RhbF9jb3VudHNfaW50LmNzdiIsIHNlcD0iXHQiLCByb3cubmFtZXMgPSAxKQoKIyMgUGlja2luZyBjb2xvcnMgZm9yIHRpbWVwb2ludHMKbWV0YV90ZW1wJGNvbG9yIDwtIGMocmVwKCIjMDAwZjNiIiwgMyksIHJlcCgiIzAwMTQ0ZSIsIDMpLCByZXAoIiMwMDE5NjIiLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCIjMDAxMTYyIiwgMyksIHJlcCgiIzAwMTc4OSIsIDMpLCByZXAoIiMwMDFlYjEiLCAzKSwKICAgICAgICAgICAgICAgICAgICByZXAoIiMxNDNiZmYiLCAzKSwgcmVwKCIjODZiY2Y5IiwgMyksIHJlcCgiI2ZmYzU3NiIsIDMpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIiNmZmQ0MDAiLCAzKSwgcmVwKCIjZmZlOTAwIiwgMyksIHJlcCgiI2ZmZjA0ZSIsIDMpLAogICAgICAgICAgICAgICAgICAgIHJlcCgiI2ZmZjU4OSIsIDMpLCByZXAoIiNjZWMwMzEiLCAzKSwgcmVwKCIjZmZiZjAwIiwgMyksCiAgICAgICAgICAgICAgICAgICAgcmVwKCIjMDAxMTYyIiwgMykpCgojIyBMb2FkaW5nIGFubm90YXRpb24gZGF0YQphbm5vdGF0aW9ucyA8LSByZWFkLmNzdigiLi4vZGF0YS9waHl0b3pvbWUvQ3JlaW5oYXJkdGlpL3Y1LjYvYW5ub3RhdGlvbi9nZW5lX2Fubm90YXRpb24udHN2IiwKICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJcdCIpCmFubm90YXRpb25zX29yZ2FuZWxsZXMgPC0gcmVhZC5jc3YoIi4uL2RhdGEvcGh5dG96b21lL0NyZWluaGFyZHRpaS92NS42L2Fubm90YXRpb24vb3JnYW5lbGxlc19hbm5vdGF0aW9uLnRzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJcdCIpCgojIC8hXCBSZW1vdmluZyBkdXBsaWNhdGVkIGdlbmVzCmFubm90YXRpb25zJGdlbmVfaWQgIDwtIG1ha2UudW5pcXVlKGFubm90YXRpb25zJGdlbmVfaWQsIHNlcD0iLiIpCgoKIyMgTWF0cml4IGNvbnZlcnNpb24KbWF0cml4X2NvdW50c19ERVNlcTIgPC0gYXMubWF0cml4KGNvdW50c19ydW5kX2RmWywyOjQ5XSkgCnJvd25hbWVzKG1hdHJpeF9jb3VudHNfREVTZXEyKSA8LSBjb3VudHNfcnVuZF9kZlssMV0KCmBgYAoKIyMgQ291bnRzIGRhdGEgbm9ybWFsaXNhdGlvbiBhbmQgdHJhbnNmb3JtYXRpb24gd2l0aCBERVNlcTIKCioqREVTZXEyOioqIAoKTG92ZSBNSSwgSHViZXIgVywgQW5kZXJzIFMgKDIwMTQpLiAiTW9kZXJhdGVkIGVzdGltYXRpb24gb2YgZm9sZCBjaGFuZ2UgYW5kIGRpc3BlcnNpb24gZm9yIFJOQSBzZXEgZGF0YSB3aXRoIERFU2VxMi4iIF9HZW5vbWUgQmlvbG9neV8sIDE1LCA1NTAuIGRvaTogMTAuMTE4Ni9zMTMwNTktMDE0LTA1NTAtOAoKYGBge3IgZGF0YV9ub3JtYWxpc2F0aW9uX3dpdGhfREVTZXEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyBOb3JtYWxpc2F0aW9uIGFuZCB0cmFuc2Zvcm1hdGlvbiBvZiBjb3VudCBkYXRhIHdpdGggREVTZXEyICMjIyMKZGRzRnVsbCA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IG1hdHJpeF9jb3VudHNfREVTZXEyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBtZXRhX3RlbXAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiB0aW1lKQoKIyMgU2l6ZSBmYWN0b3JzCmRkc0Z1bGwgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNGdWxsKQoKIyMgVGFraW5nIG91dCB1bmV4cHJlc3NlZCBnZW5lcwpkZHNGdWxsIDwtIGRkc0Z1bGxbIHJvd1N1bXMoY291bnRzKGRkc0Z1bGwpKSA+IDAsIF0KCiMjIHJsb2cgdHJhbnNmb3JtYXRpb24KcmxvZ19kYXRhIDwtIHJsb2coZGRzRnVsbCwgYmxpbmQ9VFJVRSkKYm94cGxvdChjb3VudHMoZGRzRnVsbCwgbm9ybWFsaXplZD1GQUxTRSksCiAgICAgICAgY29sID0gbWV0YV90ZW1wJGNvbG9yLAogICAgICAgIGhvcml6b250YWwgPSBUUlVFLCAKICAgICAgICBsYXMgPSAxLAogICAgICAgIGNleC5heGlzID0gMC40NSwKICAgICAgICBjZXggPSAwLjUsCiAgICAgICAgeGxhYiA9ICJyYXcgdmFsdWUiLAogICAgICAgIG1haW49IkJveHBsb3RzIG9mIHVudHJhbnNmb3JtZWQgCmdlbmUgY291bnRzIikKCmJveHBsb3QoYXNzYXkocmxvZ19kYXRhKSwKICAgICAgICBjb2wgPSBtZXRhX3RlbXAkY29sb3IsCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsIAogICAgICAgIGxhcyA9IDEsCiAgICAgICAgY2V4LmF4aXMgPSAwLjQ1LAogICAgICAgIGNleCA9IDAuNSwKICAgICAgICB4bGFiID0gInJsb2codmFsdWUpIiwKICAgICAgICBtYWluPSJCb3hwbG90cyBvZiBybG9nIHRyYW5zZm9ybWVkIApnZW5lIGNvdW50cyIpCgoKIyMgVHJhbnNmb3JtYXRpb24gdmlzdWFsaXNhdGlvbgpwYXIobWZyb3c9YygxLDIpKQpwbG90KGNvdW50cyhkZHNGdWxsLCBub3JtYWxpemVkPUZBTFNFKVssMTE6MTJdLApwY2g9MTYsIGNleD0wLjMsIHhsaW09YygwLDIwZTMpLCB5bGltPWMoMCwyMGUzKSwgbWFpbj0icmF3IGNvdW50cyIpCgpwbG90KGFzc2F5KHJsb2dfZGF0YSlbLDExOjEyXSwKcGNoPTE2LCBjZXg9MC4zLCBtYWluPSJybG9nIG5vcm1hbGl6ZWQgY291bnRzIikKcGFyKG1mcm93PWMoMSwxKSkKCmBgYAoKREVTZXEyIG5vcm1hbGlzZXMgdGhlIGRhdGEgYWNjb3JkaW5nIHRvIGxpYnJhcnkgc2l6ZSAoc2l6ZSBmYWN0b3JzKSB0aGVuIHVzZXMgYSBybG9nIHRyYW5zZm9ybWF0aW9uIHRvIGRpbWluaXNoIHRoZSBpbXBhY3Qgb2YgdmVyeSBsb3cgb3IgdmVyeSBoaWdoIGV4cHJlc3Npb24gZ2VuZXMgb24gdGhlIHN1YnNlcXVlbnQgYW5hbHlzZXMuIAoKIyMgUENBIG9mIHRyYW5zZm9ybWVkIGNvdW50cyBkYXRhCgpgYGB7ciBQQ0FfcmxvZ19kYXRhLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjkwJSIsIGZpZy5jYXA9IlBDQSBvbiBybG9nIHRyYW5zZm9ybWVkIGNvdW50IGRhdGEuIn0KIyMgcmxvZyB0cmFuc2Zvcm1lZCBkYXRhLCBQQ0EKCiMjIGV4dHJhY3QgcmxvZyBtYXRyaXgKY291bnRzX3Jsb2cgPC0gYXNzYXkocmxvZ19kYXRhKQoKIyMgUnVuIFBDQQpyZXNfcGNhIDwtIFBDQSh0KGNvdW50c19ybG9nKSwgZ3JhcGg9RkFMU0UpCgojIyBHcmFwaHMKZnZpel9laWcocmVzX3BjYSwgdGl0bGU9IlBDQSBvZiBybG9nIGRhdGEsIEVpZ2VuIHZhbHVlcyIsIGFkZGxhYmVscyA9IFRSVUUsIHlsaW0gPSBjKDAsIDUwKSkKCmZ2aXpfcGNhX2luZChyZXNfcGNhLCBsYWJlbD0ibm9uZSIsCiAgICAgICAgICAgICB0aXRsZT0iUENBIG9mIHJsb2cgZGF0YSIsCiAgICAgICAgICAgICBoYWJpbGxhZ2U9YXMuZmFjdG9yKG1ldGFfdGVtcCR0aW1lKSwKICAgICAgICAgICAgIG1lYW4ucG9pbnQ9RkFMU0UsCiAgICAgICAgICAgICBwb2ludHNoYXBlID0gMTkpIApgYGAKCk9uIHRoaXMgUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyB0aGUgY3ljbGljYWwgbmF0dXJlIG9mIHRoZSBleHBlcmltZW50IGlzIGFwcGFyZW50LiBGcm9tIHRoZSB0aW1lIHBvaW50IDBoLCB0aGUgdGltZSBwb2ludHMgZGVzY2VuZCBjb3VudGVyLWNsb2NrIHdpc2UsIHRvIHJldHVybiBhdCB0aGUgZmluYWwgMjRoIHRpbWUgcG9pbnQgYXQgdGhlIGxldmVsIG9mIHRoZSBmaXJzdCBvbmUuIE5vdGUgaG93IHRpbWUgcG9pbnRzIGF0IHRoZSBlbmQgb2YgdGhlIG5pZ2h0ICg2aCB0byAxMWgpIGFyZSBtb3JlIGNsb3NlbHkgcmVsYXRlZCB0aGVuIHRoZSBvdGhlcnMsIHRoaXMgaXMgYmVjYXVzZSBfQ2hsYW15ZG9tb25hc18gY2VsbHMgYXJlIHJlbGF0aXZlbHkgcXVpZXNjZW50IGF0IHRoaXMgcGFydCBvZiB0aGVpciBkYXkgY3ljbGUuCgojIyBIaWVyYXJjaGljYWwgY2x1c3RlcmluZyBvZiBzYW1wbGVzCgpgYGB7ciBoaWVyYXJjaGljYWxfY2x1c3RlcmluZywgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSI5MCUiLCBmaWcuY2FwPSJIaWVyYXJjaGljYWwgY2x1c3RlcmluZyBvZiBybG9nIHRyYW5zZm9ybWVkIGNvdW50IGRhdGEuIn0KCmRpc3RzIDwtIGRpc3QodChhc3NheShybG9nX2RhdGEpKSkKcGFyKG1mcm93PWMoMSwxKSkKdHJlZV9ybG9nIDwtIGhjbHVzdChkaXN0cykKCm15X2NvbG9ycyA9IGMoIiNmZmM1NzYiLCAiIzQ0NWNkNyIsICIjZmZmMDRlIiwgIiMwMDE3ODkiLCAiI2ZhZjVjNiIpCgpwYXIoYmcgPSAiZGFya2dyZXkiLCBtZnJvdz1jKDEsIDEpKQpwbG90Q29sb3JlZENsdXN0ZXJzKHRyZWVfcmxvZywgbGFicyA9IG1ldGFfdGVtcCR0aW1lLAogICAgICAgICAgICAgICAgICAgIHlsYWIgPSBOQSwgeGxhYiA9IE5BLCBjZXggPSAsIGxhcyA9IDEsCiAgICAgICAgICAgICAgICAgICAgY29scyA9IG1ldGFfdGVtcCRjb2xvciwgY29sID0gIndoaXRlIiwKICAgICAgICAgICAgICAgICAgICBtYWluID0gIlNhbXBsZXMgRXVjbGlkaWFuIGRpc3RhbmNlIGhpZXJhcmNoaWNhbCAKY2x1c3RlcmluZywgcmxvZywgY29tcGxldGUgbGlua2FnZSIpCnJlY3QuaGNsdXN0KHRyZWVfcmxvZywgaz01LCBib3JkZXI9bXlfY29sb3JzKQpwYXIoYmc9IndoaXRlIikKCgojIFNhdmluZyBjbHVzdGVycwpjbHVzdGVyc19uYW1lcyA8LSBjKCJlYXJseV9uaWdodCIsCiAgICAgICAgICAgICAgICAgICAgIm5pZ2h0IiwKICAgICAgICAgICAgICAgICAgICAiZGF3biIsCiAgICAgICAgICAgICAgICAgICAgImRheSIsCiAgICAgICAgICAgICAgICAgICAgImR1c2siKQpjbHVzdGVyc19ybG9nIDwtIGN1dHJlZSh0cmVlX3Jsb2csIGs9NSkKbWV0YV90ZW1wJGNsdXN0ZXIgPC0gY2x1c3RlcnNfbmFtZXNbY2x1c3RlcnNfcmxvZ10KCmBgYAoKVGhlIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nIG9mIHRoZSB0cmFuc2Zvcm1lZCBkYXRhIGdpdmVzIGNvaGVyZW50IGNsdXN0ZXJzLCBncm91cGluZyBzYW1wbGVzIGFjY29yZGluZyB0byB0aW1lIHBlcmlvZHMuIEluIHRoaXMgcmVwb3J0IEkgZGVjaWRlZCB0byB1c2UgdGhlc2UgY2x1c3RlcnMgdG8gc2VwYXJhdGUgdGhlIHNhbXBsZXMgaW4gdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzLgoKCiMjIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIHdpdGggREVTZXEyCkhlcmUgSSB1c2UgdGhlIHByZXZpb3VzbHkgZGVmaW5lZCBjbHVzdGVycyBhcyBmb3JtdWxhIHRvIGxvb2sgZm9yIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyB3aXRoIERFU2VxMi4gSG93ZXZlciB0aGlzIGNhbiBhbHNvIGJlIGFjaGlldmVkIGJ5IHVzaW5nIGRpcmVjdGx5IHRoZSB0aW1lIGNvbmRpdGlvbnMgKGFzIHRoZSBSIHNjcmlwdCBpbiB0aGUgd29ya2Zsb3cgZG9lcykuIAoKYGBge3IgREVHLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIyMjIERFU2VxMiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBieSB0aW1lIHBvaW50ICMjIyMKZGRzVGltZXMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSBtYXRyaXhfY291bnRzX0RFU2VxMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IG1ldGFfdGVtcCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiBjbHVzdGVyKSAjIH4gdGltZV9mYWN0b3IgY291bGQgYmUgdXNlZCBpbnN0ZWFkCgojIyBFbGltaW5hdGlvbiBvZiBsb3dseSBleHByZXNzZWQgZ2VuZXMKCmRkc1RpbWVzIDwtIGRkc1RpbWVzWyByb3dTdW1zKGNvdW50cyhkZHNUaW1lcykpID4gNjAsIF0KCiMjIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzCmRkc1RpbWVzIDwtIERFU2VxKGRkc1RpbWVzKQp0aW1lX3BvaW50cyA8LSB1bmlxdWUobWV0YV90ZW1wJGNsdXN0ZXIpICMgdGltZV9mYWN0b3IgY291bGQgYmUgdXNlZCBpbnN0ZWFkCgp0aW1lX3JlcCA8LSBjKHJlcCh0aW1lX3BvaW50cywgYygxLCByZXAoMiwgbGVuZ3RoKHRpbWVfcG9pbnRzKS0xKSkpLCB0aW1lX3BvaW50c1sxXSkKcGFpcnMgPC0gbWF0cml4KGFzLmZhY3Rvcih0aW1lX3JlcCksIG5jb2wgPSAyLCBieXJvdyA9IFRSVUUpCgoKIyBTaWduaWZpY2FudCBnZW5lcyBpbml0aWFsaXNhdGlvbgpzaWduaWZpY2FudF9nZW5lcyA8LSBjKCkKCiMgRXh0cmFjdGlvbiBvZiBERVNlcTIgcmVzdWx0cwpmb3IgKGkgaW4gKDEgOiBucm93KHBhaXJzKSkpIHsKICAgIGVsZSA8LSBwYWlyc1tpLF0KICAgIHRleHQgPC0gcGFzdGUwKGVsZVsxXSwgIi8iLCBlbGVbMl0sICIgREVHOiIpCiAgICByZXNERVNlcSA8LSByZXN1bHRzKGRkc1RpbWVzLCBjb250cmFzdCA9IGMoImNsdXN0ZXIiLCBlbGVbMV0sIGVsZVsyXSksICMgInRpbWVfZmFjdG9yIiBjb3VsZCBiZSB1c2VkIGluc3RlYWQKICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXBlbmRlbnRGaWx0ZXJpbmcgPSBUUlVFLCBhbHBoYT0wLjAxKQogICAgbWVzc2FnZSh0ZXh0KQogICAgbWVzc2FnZSggc3VtKCByZXNERVNlcSRwYWRqIDwgMC4wMSwgbmEucm09VFJVRSApICkKICAgIHRlbXBfbGlzdCA8LSByb3cubmFtZXMocmVzREVTZXFbd2hpY2gocmVzREVTZXEkcGFkaiA8IDAuMDEpLF0pCiAgICBtZXNzYWdlKHBhc3RlMChjKGxlbmd0aCh0ZW1wX2xpc3QpL25yb3coY291bnRzX3J1bmRfZGYpICogMTAwKSwgIiAlIikpCiAgICBzaWduaWZpY2FudF9nZW5lcyA8LSB1bmlvbih0ZW1wX2xpc3QsIHNpZ25pZmljYW50X2dlbmVzKQp9CgpwcmludChwYXN0ZTAoIlRvdGFsIERFRyBpbiBhdCBsZWFzdCBvbmUgdGltZSB0cmFuc2l0aW9uOiAiLCAobGVuZ3RoKHNpZ25pZmljYW50X2dlbmVzKS9ucm93KGNvdW50c19ydW5kX2RmKSAqIDEwMCksICIgJSIpKQoKc2lnbl9kZiA8LSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHNpZ25pZmljYW50X2dlbmVzKQpzaWduX2RmJGRpZmZfZXhwciA8LSAieWVzIgpzaWduX2RmJGdlbmVfaWQgPC0gcm93Lm5hbWVzKHNpZ25fZGYpCgoKYGBgClRoZSB1c2Ugb2YgdGltZSBjb25kaXRpb24gKGFzIGluIHRoZSB3b3JrZmxvdyBSIHNjcmlwdCkgaW5zdGVhZCBvZiB0aGUgY2x1c3RlcnMgZ2l2ZXMgbGVzcyBERUcsIGFib3V0IDcwJS4KCiMjIFJoeXRobSBhbmFseXNpcyB3aXRoIERpc2NvUmh5dGhtCgoqKkRpc2NvUmh5dGhtOioqCgpNYXR0aGV3IENhcmx1Y2NpLCBBbGdpbWFudGFzIEtyacWhxI1pxatuYXMsIEhhb2hhbiBMaSwgUG92aWxhcyBHaWJhcywgS2Fyb2xpcyBLb25jZXZpxI1pdXMsIEFydCBQZXRyb25pcywgR2FicmllbCBPaCwgRGlzY29SaHl0aG06IGFuIGVhc3ktdG8tdXNlIHdlYiBhcHBsaWNhdGlvbiBhbmQgUiBwYWNrYWdlIGZvciBkaXNjb3ZlcmluZyByaHl0aG1pY2l0eSwgX0Jpb2luZm9ybWF0aWNzXywgVm9sdW1lIDM2LCBJc3N1ZSA2LCAxNSBNYXJjaCAyMDIwLCBQYWdlcyAxOTUy4oCTMTk1NCwgaHR0cHM6Ly9kb2kub3JnLzEwLjEwOTMvYmlvaW5mb3JtYXRpY3MvYnR6ODM0CgpgYGB7ciByaHl0aG1fYW5hbHlzaXNfRGlzY29SaHl0aG19CgojIENvbnZlcnRpbmcgcmxvZyBtYXRyaXggaW4gU0UgKFN1Ym1hcmlzZWQgRXhwZXJpbWVudCkpCmdlbmVfaWQgPC0gcm93Lm5hbWVzKGNvdW50c19ybG9nKQpybG9nX2RmIDwtIGFzLmRhdGEuZnJhbWUoY291bnRzX3Jsb2cpCnJsb2dfZGYgPC0gYWRkX2NvbHVtbihybG9nX2RmLCBnZW5lX2lkLCAuYmVmb3JlPTEpCmlucHV0X2RhdGEgPC0gZGlzY29ERnRvU0UocmxvZ19kZikKCmRpc2NvRGVzaWduU3VtbWFyeShpbnB1dF9kYXRhKQoKIyBPdXIgdGltZXBvaW50cyBhcmUgbm90IGVxdWlkaXN0YW50LCB3ZSBjYW4gdXNlIGVpdGhlciB0aGUgY29zaW5vciBvciBMb21iLVNjYXJnbGUgbWV0aG9kIHRvIGRldGVjdCBmZWF0dXJlIHJoeXRobXMKCiMgQ29zaW5vcgpyeXRobXNfZ2VuZXNfQ1MgPC0gZGlzY29PREFzKGlucHV0X2RhdGEsIHBlcmlvZCA9IDI0LCBtZXRob2QgPSAiQ1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpcmN1bGFyX3QgPSBUUlVFLCBuY29yZXMgPSA0KQoKIyBMb21iLVNjYXJnbGUKcnl0aG1zX2dlbmVzX0xTIDwtIGRpc2NvT0RBcyhpbnB1dF9kYXRhLCBwZXJpb2QgPSAyNCwgbWV0aG9kID0gIkxTIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lyY3VsYXJfdCA9IFRSVUUsIG5jb3JlcyA9IDQpCgoKcGFyKG1mcm93PWMoMSwyKSkKaGlzdChkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19DUykkQ1MucXZhbHVlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAicXZhbHVlIGNvc2lub3IiLAogICAgIHhsYWIgPSAicXZhbHVlIikKaGlzdChkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19MUykkTFMucXZhbHVlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAicXZhbHVlIExvbWItU2NhcmdsZSIsCiAgICAgeGxhYiA9ICJxdmFsdWUiKQpgYGAKClRoZSBMb21iLVNjYXJnbGUgcXZhbHVlIGRpc3RyaWJ1dGlvbiBoYXMgYSBwcm9ibGVtYXRpYyBwcm9maWxlLCB3ZSB3aWxsIGZvY3VzIG9uIENvc2lub3IuCgpgYGB7ciBjb3Npbm9yX3JoeXRobWljX2dlbmVzfQojIEV4dHJhY3RpbmcganVzdCB0aGUgZGF0YWZyYW1lcyBmcm9tIHRoZSBkaXNjb3J5dGhtIG91dHB1dApDU19kZiA8LSBkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19DUykKCgojIFJldHJlaXZpbmcgb25seSBtb3N0IHNpZ25pZmljYW50IGdlbmVzIAojIHF2YWx1ZSBpbmZlcmlvciB0byAwLjA1CkNTX2RmIDwtIENTX2RmW0NTX2RmJENTLnF2YWx1ZSA8IDAuMDUsXQoKCnBhcihtZnJvdz1jKDEsMikpCmhpc3QoQ1NfZGYkQ1MuYW1wbGl0dWRlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAiYW1wbGl0dWRlcyBjb3Npbm9yIAphZnRlciBzZWxlY3Rpb24iLAogICAgIHhsYWIgPSAiYW1wbGl0dWRlIikKCmhpc3QoQ1NfZGYkQ1MuYWNyb3BoYXNlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAiYWNyb3BoYXNlcyBjb3Npbm9yIAphZnRlciBzZWxlY3Rpb24iLAogICAgIHhsYWIgPSAiaG91ciIpCnBhcihtZnJvdz1jKDEsMSkpCgpgYGAKClRoZSBhY3JvcGhhc2UgaXMgdGhlIHRpbWUgd2hlbiB0aGUgZXhwcmVzc2lvbiBvZiB0aGUgZ2VuZSBwZWFrcy4gV2Ugd2lsbCBmb2N1cyBvbiB0aGUgYWNyb3BoYXNlIHBhcmFtZXRlciBpbnN0ZWFkIG9mIHRoZSBhbXBsaXR1ZGUgb2YgdGhlIGV4cHJlc3Npb24gc2lnbmFsIHRvIGZpbmQgcHV0YXRpdmUgcmVndWxhdG9ycy4gSW5kZWVkLCB3aGF0IHdlIGFyZSBpbnRlcmVzdGVkIGluIGlzIG5vdCB0aGUgaW50ZW5zaXR5IG9mIGdlbmUgZXhwcmVzc2lvbiwgYnV0IHJhdGhlciB0aGUgdGltaW5nIG9mIGV4cHJlc3Npb24uCgojIyBBbm5vdGF0aW9uCgpgYGB7ciBhbm5vdGF0aW9uX29mX2RhdGF9CgojIyBFeHRyYWN0aW9uIG9mIGFubm90YXRpb25zCnJvd19DUyA8LSByb3cubmFtZXMoQ1NfZGYpCgpDU19kZiRnZW5lX2lkIDwtIHJvd19DUwoKQ1NfZGYgPC0gbGVmdF9qb2luKENTX2RmLCBhbm5vdGF0aW9ucykKCmlkX29yZ2FuZWxsZSA9IGFubm90YXRpb25zX29yZ2FuZWxsZXMkZ2VuZV9pZApyb3cubmFtZXMoYW5ub3RhdGlvbnNfb3JnYW5lbGxlcykgPC0gaWRfb3JnYW5lbGxlCgpyb3dfQ1MgLT4gcm93Lm5hbWVzKENTX2RmKQoKCmZvciAoaWQgaW4gaWRfb3JnYW5lbGxlKSB7CiAgICBDU19kZltpZCwgImdlbmVfc3ltYm9sIl0gPC0gYW5ub3RhdGlvbnNfb3JnYW5lbGxlc1tpZCwiZ2VuZV9zeW1ib2wiXQp9CgoKQ1NfZGYkZ2VuZV9pZCA8LSByb3cubmFtZXMoQ1NfZGYpCgpDU19kZiRlbmNvZGVkIDwtICJOdWNsZXVzIgoKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2lkLCAiQ3JlTXQuIikpLCAiZW5jb2RlZCJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJlbmNvZGVkIl0gPC0gIkNobG9yb3BsYXN0IgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVNdC4iKSksICJzdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJzdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJDaGxvcm9wbGFzdCIKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2lkLCAiQ3JlTXQuIikpLCAic2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uIl0gPC0gIkNobG9yb3BsYXN0IgoKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2Rlc2NyaXB0aW9uLCAiT2N0b3RyaWNvUGVwdGlkZSIpID09IFRSVUUpLCBdIC0+IENTX3N1YnNldF9vcHIKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2Rlc2NyaXB0aW9uLCAiUGVudGF0cmljb1BlcHRpZGUiKSA9PSBUUlVFKSwgXSAtPiBDU19zdWJzZXRfcHByCgoKIyBHZW5lcyBib3RoIHJoeXRobWljIGFuZCBERQpmaW5hbF9kYXRhIDwtIGxlZnRfam9pbihDU19kZiwgc2lnbl9kZiwgYnkgPSAiZ2VuZV9pZCIpCmZpbmFsX2RhdGEgPC0gZmluYWxfZGF0YVt3aGljaChmaW5hbF9kYXRhJGRpZmZfZXhwciA9PSAieWVzIiksXQpmaW5hbF9kYXRhIDwtIGZpbmFsX2RhdGFbIHdoaWNoKCFpcy5uYShmaW5hbF9kYXRhJENTLmFjcm9waGFzZSkpICwgXQoKYGBgCgojIyBHZW5lcmFsIHZpZXcgb2Ygcmh5dGhtaWMgZ2VuZXMgYWNyb3BoYXNlcwoKYGBge3IgZ2VuZXNfYWNyb3BoYXNlcywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NSwgb3V0LndpZHRoPSI5MCUiLCBmaWcuY2FwPSJBY3JvcGhhc2VzIGRpc3RyaWJ1dGlvbi4ifQpnZ3Bsb3QoZGF0YSA9IGZpbmFsX2RhdGEsIG1hcHBpbmcgPSBhZXMoeD1DUy5hY3JvcGhhc2UsIGZpbGw9ZW5jb2RlZCkpKwogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBDUy5hY3JvcGhhc2UsIHkgPSAuLmRlbnNpdHkuLiksIGJpbndpZHRoID0gMC41KSArCiAgICBmYWNldF93cmFwKH5lbmNvZGVkKSArCiAgICBsYWJzKCB4ID0gIkFjcm9waGFzZSIsIHkgPSAiR2VuZXMiLAogICAgICAgICAgdGl0bGUgPSJBY3JvcGhhc2VzIGRpc3RyaWJ1dGlvbiBhY2NvcmRpbmcgdG8gZW5jb2RpbmcgZ2Vub21lIiwKICAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOTllNTVjIiwgIiNlYjk1N2MiLCAiIzBmYzZlMSIpKQoKCgpjKHBhc3RlMCgiQ2hsb3JvcGxhc3QiLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaGxvcm9wbGFzdCIsXSksICIpIiksCiAgcGFzdGUwKCJDaHJvbW9zb21lIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hyb21vc29tZSIsXSksICIpIiksCiAgcGFzdGUwKCJDaWxpdW0iLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaWxpdW0iLF0pLCAiKSIpLAogIHBhc3RlMCgiQ3l0b3BsYXNtIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ3l0b3BsYXNtIixdKSwgIikiKSwKICBwYXN0ZTAoIkN5dG9za2VsZXRvbiIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIkN5dG9za2VsZXRvbiIsXSksICIpIiksCiAgcGFzdGUwKCJFbmRvcGxhc21pYyByZXRpY3VsdW0iLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJFbmRvcGxhc21pYyByZXRpY3VsdW0iLF0pLCAiKSIpLAogIHBhc3RlMCgiR29sZ2kgYXBwYXJhdHVzIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiR29sZ2kgYXBwYXJhdHVzIixdKSwgIikiKSwgICAKICBwYXN0ZTAoIk1lbWJyYW5lIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiTWVtYnJhbmUiLF0pLCAiKSIpLAogIHBhc3RlMCgiTWl0b2Nob25kcmlvbiIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk1pdG9jaG9uZHJpb24iLF0pLCAiKSIpLAogIHBhc3RlMCgiTnVjbGV1cyIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk51Y2xldXMiLF0pLCAiKSIpLAogIHBhc3RlMCgiT3RoZXIiLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJPdGhlciIsXSksICIpIiksCiAgcGFzdGUwKCJ1bmtub3duIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAidW5rbm93biIsXSksICIpIikpIC0+IGxvY2F0aW9ucwogICAKI2ZpbmFsX2RhdGEyIDwtIGZpbHRlcihmaW5hbF9kYXRhLCBzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uICE9ICJ1bmtub3duIikKCmdncGxvdChkYXRhID0gZmluYWxfZGF0YSwgbWFwcGluZyA9IGFlcyh4PUNTLmFjcm9waGFzZSwgZmlsbD1zaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uKSkrCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0wLCB5bWF4ID0gSW5mLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0wLCB5bWF4ID0gSW5mLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTAsIHltYXggPSBJbmYsIGFscGhhID0wLjMpKwogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBDUy5hY3JvcGhhc2UsIHkgPSAuLmRlbnNpdHkuLiksIGJpbndpZHRoID0gMC4zKSArCiAgICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgYWxwaGE9MC41KSArCiAgICBmYWNldF93cmFwKH5zaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uKSsKICAgIGxhYnMoIHggPSAiQWNyb3BoYXNlIiwgeSA9ICJHZW5lcyIsCiAgICAgICAgICAgIHRpdGxlID0iQWNyb3BoYXNlcyBkaXN0cmlidXRpb24gYWNjb3JkaW5nIHRvIGNlbGx1bGFyIGxvY2F0aW9uIiwKICAgICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJDZWxsdWxhciBsb2NhdGlvbiIsIGxhYmVscyA9IGxvY2F0aW9ucykKCmBgYAoKIyMgUHV0YXRpdmUgYW5kIGtub3duIHJlZ3VsYXRvcnMKCmBgYHtyIE9UQUZ9CiMgUmVjb3ZlcmluZyBzb21lIHJoeXRobWljIE9UQUZzCm9wciA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9kZXNjcmlwdGlvbiwgIk9jdG90cmljb1BlcHRpZGUgUmVwZWF0IikpICwgXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCnBwciA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9kZXNjcmlwdGlvbiwgIlBlbnRhdHJpY29QZXB0aWRlIFJlcGVhdCIpKSAsIF0KdHByIDwtIGZpbmFsX2RhdGFbIHdoaWNoKHN0YXJ0c1dpdGgoZmluYWxfZGF0YSRnZW5lX2Rlc2NyaXB0aW9uLCAiVGV0cmF0cmljb1BlcHRpZGUgUmVwZWF0IikpICwgXQoKb3RhZiA8LSB1bmlvbl9hbGwob3ByLCBwcHIpCm90YWYgPC0gdW5pb25fYWxsKG90YWYsIHRwcikKCiMgQWRkaW5nIGV4cHJlc3Npb24gZGF0YToKY29sdW1ucyA8LSBjb2xuYW1lcyhvdGFmKQpvdGFmIDwtIGxlZnRfam9pbihvdGFmLCBybG9nX2RmKQpjb2xuYW1lcyhvdGFmKSA8LSBtYWtlLnVuaXF1ZShjKGNvbHVtbnMsIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpKSkKCiMgUHJlZGljdGVkIGNobG9yb3BsYXN0IGltcG9ydGVkIE9UQUZzCm11bHRpX290YWZfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiKSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG11bHRpX290YWZfY2hsb3JvIDwtIHJiaW5kKG11bHRpX290YWZfY2hsb3JvLCB0bXBfZGYpCn0KCm11bHRpX290YWZfY2hsb3JvIDwtIG11bHRpX290YWZfY2hsb3JvWy0xLF0KCiMgUHJlZGljdGVkIG1pdG9jaG9uZHJpb24gaW1wb3J0ZWQgT1RBRnMKbXVsdGlfb3RhZl9taXRvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiTWl0b2Nob25kcmlvbiIpLF0kZ2VuZV9zeW1ib2wpewogICAgb3RhZltvdGFmJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgbXVsdGlfb3RhZl9taXRvIDwtIHJiaW5kKG11bHRpX290YWZfbWl0bywgdG1wX2RmKQp9CgptdWx0aV9vdGFmX21pdG8gPC0gbXVsdGlfb3RhZl9taXRvWy0xLF0KCmBgYAoKYGBge3Igb3JnYW5lbGxlc19nZW5lc30KCiMgRXh0cmFjdGluZyBvcmdhbmVsbGFyIHJoeXRobWljIGdlbmVzCmNobG9ybyA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9pZCwgIkNyZUNwIikpICwgXQptaXRvIDwtIGZpbmFsX2RhdGFbIHdoaWNoKHN0YXJ0c1dpdGgoZmluYWxfZGF0YSRnZW5lX2lkLCAiQ3JlTXQiKSkgLCBdCgoKIyBBZGRpbmcgZXhwcmVzc2lvbiBkYXRhOgpjb2x1bW5zIDwtIGNvbG5hbWVzKGNobG9ybykKY2hsb3JvIDwtIGxlZnRfam9pbihjaGxvcm8sIHJsb2dfZGYpCmNvbG5hbWVzKGNobG9ybykgPC0gbWFrZS51bmlxdWUoYyhjb2x1bW5zLCByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKSkpCmNobG9ybyRnZW5lX3N5bWJvbCA8LSBtYWtlLnVuaXF1ZShjaGxvcm8kZ2VuZV9zeW1ib2wpCgpjb2x1bW5zIDwtIGNvbG5hbWVzKG1pdG8pCm1pdG8gPC0gbGVmdF9qb2luKG1pdG8sIHJsb2dfZGYpCmNvbG5hbWVzKG1pdG8pIDwtIG1ha2UudW5pcXVlKGMoY29sdW1ucywgcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykpKQoKCiMgQ2hsb3JvcGxhc3QKbXVsdGlfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIGNobG9ybyRnZW5lX3N5bWJvbCl7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgbXVsdGlfY2hsb3JvIDwtIHJiaW5kKG11bHRpX2NobG9ybywgdG1wX2RmKQp9CgptdWx0aV9jaGxvcm8gPC0gbXVsdGlfY2hsb3JvWy0xLF0KCgojIE1pdG9jaG9uZHJpb24KbXVsdGlfbWl0byA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBtaXRvJGdlbmVfc3ltYm9sKXsKICAgIG1pdG9bbWl0byRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG11bHRpX21pdG8gPC0gcmJpbmQobXVsdGlfbWl0bywgdG1wX2RmKQp9CgptdWx0aV9taXRvIDwtIG11bHRpX21pdG9bLTEsXQoKCmBgYAoKYGBge3IgZ2VuZV9leHByZXNzaW9uX21vZGVsX3Bsb3RzLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01LCBmaWcuY2FwPSJHZW5lIGV4cHJlc3Npb24gbW9kZWxzLiJ9CnBlcmlvZGU9MjQKCmdncGxvdChkYXRhID0gbXVsdGlfb3RhZl9jaGxvcm8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIGNobG9yb3BsYXN0IGxvY2FsaXNlZCBPVEFGcywgZXhwcmVzc2lvbiBtb2RlbHM6IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKCgpnZ3Bsb3QoZGF0YSA9IG11bHRpX2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGxldmVsID0gMC45NSwKICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiAgICAgICAgICAgICAgICBmdWxscmFuZ2UgPSBUUlVFKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBsYWJzKHkgPSAicmxvZyhjb3VudHMpIiwgeCA9ICJUaW1lIChoKSIsCiAgICAgICAgIHRpdGxlID0iUmh5dGhtaWMgY2hsb3JvcGxhc3QgZ2VuZXMsIGV4cHJlc3Npb24gbW9kZWxzOiIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgoKZ2dwbG90KGRhdGEgPSBtdWx0aV9vdGFmX21pdG8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIG1pdG9jaG9uZHJpb24gbG9jYWxpc2VkIE9UQUZzLCBleHByZXNzaW9uIG1vZGVsczoiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQoKCgpnZ3Bsb3QoZGF0YSA9IG11bHRpX21pdG8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIG1pdG9jaG9uZHJpb24gZ2VuZXMsIGV4cHJlc3Npb24gbW9kZWxzOiIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgpgYGAKCgpUbyBwYWlyIE9UQUZzIGFuZCB0aGVpciBwdXRhdGl2ZSBvcmdhbmVsbGFyIG1STkEgdGFyZ2V0cyB3ZSBtdXN0IGxvb2sgYXQ6IAoKLSBPVEFGcyBhbmQgbVJOQSBsb2NhbGlzZWQgaW4gdGhlIHNhbWUgb3JnYW5lbGxlCgotIFdpdGggYWNyb3BoYXNlcyBvZmZzZXQgYnkgYSBmZXcgaG91cnMuIEZyb20gbVJOQSB0aGUgT1RBRiBtdXN0IGJlIHRyYW5zbGF0ZWQsIHRoZW4gaW1wb3J0ZWQgaW50byB0aGUgb3JnYW5lbGxlIHdoZXJlIGl0IG1pZ2h0IGFjdCBvbiBpdHMgbVJOQSB0YXJnZXQuIEhlcmUgSSB1c2VkIGEgNCBob3VycyBzaGlmdGVkIHBvdGVudGlhbCB3aW5kb3cuCgpgYGB7ciBPVEFGX21STkFfcGFpcnMsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkNhbmRpZGF0ZSBPVEFGL21STkEgdGFyZ2V0IHBhaXJzLiJ9CmFjcm9fbW9ybmluZ19jaGxvcm8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gY2hsb3JvW3doaWNoKGNobG9ybyRDUy5hY3JvcGhhc2UgPDE2ICYgY2hsb3JvJENTLmFjcm9waGFzZSA+MTIgKSxdJGdlbmVfc3ltYm9sKSB7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19tb3JuaW5nX2NobG9ybyA8LSByYmluZChhY3JvX21vcm5pbmdfY2hsb3JvLCB0bXBfZGYpCn0KCmFjcm9fbW9ybmluZ19jaGxvcm8gPC0gYWNyb19tb3JuaW5nX2NobG9yb1stMSxdCgoKb3RhZl9jaGxvcm9fYWNyb19kYXduIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiICYgb3RhZiRDUy5hY3JvcGhhc2UgPDEyICYgb3RhZiRDUy5hY3JvcGhhc2UgPjgpLF0kZ2VuZV9zeW1ib2wpewogICAgb3RhZltvdGFmJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgb3RhZl9jaGxvcm9fYWNyb19kYXduIDwtIHJiaW5kKG90YWZfY2hsb3JvX2Fjcm9fZGF3biwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX2Rhd24gPC0gb3RhZl9jaGxvcm9fYWNyb19kYXduWy0xLF0KCgojIFBsb3RzIAoKZ2dwbG90KGRhdGEgPSBvdGFmX2NobG9yb19hY3JvX2Rhd24sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMykgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZGF3biIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKCmdncGxvdChkYXRhID0gYWNyb19tb3JuaW5nX2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIHlsaW0oMTAsIDIxKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0xMCwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMCwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTEwLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBtUk5BLCBhY3JvcGhhc2UgaW4gdGhlIG1vcm5pbmciLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKYGBgCgpIZXJlLCB3ZSBjYW4gaWRlbnRpZnkga25vd24gT1RBRi9jaGxvcm9wbGFzdCBtUk5BIHBhaXJzL3RyaW9zOgoKLSBNREExLCBUREExIGFuZCBfYXRwQV8KCi0gTURIMSAoTVRISTEpLCBfYXRwSF8gYW5kIF9hdHBJXwoKLSBDQ1MyIGFuZCBfY2NzQV8KCi0gTUNHMSBhbmQgX3BldEdfCgoKQnV0IGFsc28gb3RoZXIgcG90ZW50aWFsIE9UQUYvbVJOQSBwYWlycyEKCgpgYGB7ciBPVEFGX21STkFfcGFpcnMyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01LCBmaWcuY2FwPSJDYW5kaWRhdGUgT1RBRi9tUk5BIHRhcmdldCBwYWlycy4ifQphY3JvX2FmdGVybm9vbl9jaGxvcm8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gY2hsb3JvW3doaWNoKGNobG9ybyRDUy5hY3JvcGhhc2UgPDIwICYgY2hsb3JvJENTLmFjcm9waGFzZSA+MTYgKSxdJGdlbmVfc3ltYm9sKSB7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19hZnRlcm5vb25fY2hsb3JvIDwtIHJiaW5kKGFjcm9fYWZ0ZXJub29uX2NobG9ybywgdG1wX2RmKQp9CgphY3JvX2FmdGVybm9vbl9jaGxvcm8gPC0gYWNyb19hZnRlcm5vb25fY2hsb3JvWy0xLF0KCgpvdGFmX2NobG9yb19hY3JvX2RheSA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBvdGFmW3doaWNoKG90YWYkc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIkNobG9yb3BsYXN0IiAmIG90YWYkQ1MuYWNyb3BoYXNlIDwxNiAmIG90YWYkQ1MuYWNyb3BoYXNlID4xMiksXSRnZW5lX3N5bWJvbCl7CiAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICBvdGFmX2NobG9yb19hY3JvX2RheSA8LSByYmluZChvdGFmX2NobG9yb19hY3JvX2RheSwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX2RheSA8LSBvdGFmX2NobG9yb19hY3JvX2RheVstMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gb3RhZl9jaGxvcm9fYWNyb19kYXksIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMSwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZGF3biIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKCmdncGxvdChkYXRhID0gYWNyb19hZnRlcm5vb25fY2hsb3JvLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgeWxpbSgxMiwgMjEpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAyMywgeG1heCA9IEluZiwgeW1pbiA9MTIsIHltYXggPSAyMSwgYWxwaGEgPTAuMykrCiAgICBmYWNldF93cmFwKH5nZW5lKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IkNobG9yb3BsYXN0IG1STkEsIGFjcm9waGFzZSBhdCBkYXkiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKYGBgCgpIZXJlLCB3ZSBjYW4gaWRlbnRpZnkga25vd24gT1RBRi9jaGxvcm9wbGFzdCBtUk5BIHBhaXJzOgoKLSBNQUMxIGFuZCBfcHNhQ18KCi0gTUJCMSBhbmQgX3BzYkJfIAoKLSBNQkMxIGFuZCBfcHNiQ18KCi0gVEFBMSBhbmQgX3BzYUFfCgotIFRCQzIgYW5kIF9wc2JDXwoKLSBUQUIxIGFuZCBfcHNhQl8KCkFuZCBvdGhlciBwb3RlbnRpYWwgT1RBRi9tUk5BIHBhaXJzLi4uCgoKYGBge3IgT1RBRl9tUk5BX3BhaXJzMywgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmNhcD0iQ2FuZGlkYXRlIE9UQUYvbVJOQSB0YXJnZXQgcGFpcnMuIn0KYWNyb19ldmVuaW5nX2NobG9ybyA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBjaGxvcm9bd2hpY2goY2hsb3JvJENTLmFjcm9waGFzZSA8MjQgJiBjaGxvcm8kQ1MuYWNyb3BoYXNlID4yMCApLF0kZ2VuZV9zeW1ib2wpIHsKICAgIGNobG9yb1tjaGxvcm8kZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgICAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgICAgICBhY3JvX2V2ZW5pbmdfY2hsb3JvIDwtIHJiaW5kKGFjcm9fZXZlbmluZ19jaGxvcm8sIHRtcF9kZikKfQoKYWNyb19ldmVuaW5nX2NobG9ybyA8LSBhY3JvX2V2ZW5pbmdfY2hsb3JvWy0xLF0KCgpvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBvdGFmW3doaWNoKG90YWYkc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIkNobG9yb3BsYXN0IiAmIG90YWYkQ1MuYWNyb3BoYXNlIDwyMCAmIG90YWYkQ1MuYWNyb3BoYXNlID4xNiksXSRnZW5lX3N5bWJvbCl7CiAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICBvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiA8LSByYmluZChvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiA8LSBvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vblstMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gb3RhZl9jaGxvcm9fYWNyb19hZnRlcm5vb24sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMSwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZGF5IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgoKI2dncGxvdChkYXRhID0gYWNyb19ldmVuaW5nX2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKIyAgICB5bGltKDEyLCAyMSkgKwojICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKIyAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiMgICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSsKIyAgICBmYWNldF93cmFwKH5nZW5lKSArCiMgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAojICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiMgICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwojICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwojICAgIGdlb21fcG9pbnQoKSArCiMgICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAojICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBtUk5BLCBhY3JvcGhhc2UgaW4gZXZlbmluZyIsCiMgICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwojICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKIyAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKcHJpbnQoIk5vIGNobG9yb3BsYXN0IGdlbmUgd2l0aCBtYXggZXhwcmVzc2lvbiBhdCBkdXNrLiIpCgpgYGAKCgoKCmBgYHtyIE9UQUZfbVJOQV9wYWlyczQsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkNhbmRpZGF0ZSBPVEFGL21STkEgdGFyZ2V0IHBhaXJzLiJ9CmFjcm9fbmlnaHRfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIGNobG9yb1t3aGljaChjaGxvcm8kQ1MuYWNyb3BoYXNlIDw0ICYgY2hsb3JvJENTLmFjcm9waGFzZSA+MCApLF0kZ2VuZV9zeW1ib2wpIHsKICAgIGNobG9yb1tjaGxvcm8kZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgICAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgICAgICBhY3JvX25pZ2h0X2NobG9ybyA8LSByYmluZChhY3JvX25pZ2h0X2NobG9ybywgdG1wX2RmKQp9CgphY3JvX25pZ2h0X2NobG9ybyA8LSBhY3JvX25pZ2h0X2NobG9yb1stMSxdCgoKb3RhZl9jaGxvcm9fYWNyb19kdXNrIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiICYgb3RhZiRDUy5hY3JvcGhhc2UgPDI0ICYgb3RhZiRDUy5hY3JvcGhhc2UgPjIwKSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG90YWZfY2hsb3JvX2Fjcm9fZHVzayA8LSByYmluZChvdGFmX2NobG9yb19hY3JvX2R1c2ssIHRtcF9kZikKfQoKb3RhZl9jaGxvcm9fYWNyb19kdXNrIDwtIG90YWZfY2hsb3JvX2Fjcm9fZHVza1stMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gb3RhZl9jaGxvcm9fYWNyb19kdXNrLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9NCwgeW1heCA9IDgsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSA4LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTQsIHltYXggPSA4LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIHlsaW0oNCwgOCkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZHVzayIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKCmdncGxvdChkYXRhID0gYWNyb19uaWdodF9jaGxvcm8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICB5bGltKDExLCAxNikgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9MTEsIHltYXggPSAxNiwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImdvbGQiLCB4bWluID0gMTEsIHhtYXggPSAyMywgeW1pbiA9MTEsIHltYXggPSAxNiwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID0xMSwgeW1heCA9IDE2LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGxldmVsID0gMC45NSwKICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiAgICAgICAgICAgICAgICBmdWxscmFuZ2UgPSBUUlVFKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBsYWJzKHkgPSAicmxvZyhjb3VudHMpIiwgeCA9ICJUaW1lIChoKSIsCiAgICAgICAgIHRpdGxlID0iQ2hsb3JvcGxhc3QgbVJOQSwgYWNyb3BoYXNlIGluIGVhcmx5IG5pZ2h0IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCmBgYAoKYGBge3IgT1RBRl9tUk5BX3BhaXJzNSwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmNhcD0iQ2FuZGlkYXRlIE9UQUYvbVJOQSB0YXJnZXQgcGFpcnMuIn0KYWNyb19uaWdodF9jaGxvcm8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gY2hsb3JvW3doaWNoKGNobG9ybyRDUy5hY3JvcGhhc2UgPDggJiBjaGxvcm8kQ1MuYWNyb3BoYXNlID40ICksXSRnZW5lX3N5bWJvbCkgewogICAgY2hsb3JvW2NobG9ybyRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICAgICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgICAgIGFjcm9fbmlnaHRfY2hsb3JvIDwtIHJiaW5kKGFjcm9fbmlnaHRfY2hsb3JvLCB0bXBfZGYpCn0KCmFjcm9fbmlnaHRfY2hsb3JvIDwtIGFjcm9fbmlnaHRfY2hsb3JvWy0xLF0KCgpvdGFmX2NobG9yb19hY3JvX25pZ2h0IDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiICYgb3RhZiRDUy5hY3JvcGhhc2UgPDQgJiBvdGFmJENTLmFjcm9waGFzZSA+MCksXSRnZW5lX3N5bWJvbCl7CiAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICBvdGFmX2NobG9yb19hY3JvX25pZ2h0IDwtIHJiaW5kKG90YWZfY2hsb3JvX2Fjcm9fbmlnaHQsIHRtcF9kZikKfQoKb3RhZl9jaGxvcm9fYWNyb19uaWdodCA8LSBvdGFmX2NobG9yb19hY3JvX25pZ2h0Wy0xLF0KCgojIFBsb3RzIAoKZ2dwbG90KGRhdGEgPSBvdGFmX2NobG9yb19hY3JvX25pZ2h0LCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9NCwgeW1heCA9IDksIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSA5LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTQsIHltYXggPSA5LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIHlsaW0oNCwgOSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgaW4gZWFybHkgbmlnaHQiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCgpnZ3Bsb3QoZGF0YSA9IGFjcm9fbmlnaHRfY2hsb3JvLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgeWxpbSgxMiwgMTYpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTEyLCB5bWF4ID0gMTYsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTEyLCB5bWF4ID0gMTYsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAyMywgeG1heCA9IEluZiwgeW1pbiA9MTIsIHltYXggPSAxNiwgYWxwaGEgPTAuMykrCiAgICBmYWNldF93cmFwKH5nZW5lKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IkNobG9yb3BsYXN0IG1STkEsIGFjcm9waGFzZSBhdCBuaWdodCIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgpgYGAKCmBgYHtyIE9UQUZfbVJOQV9wYWlyczYsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkNhbmRpZGF0ZSBPVEFGL21STkEgdGFyZ2V0IHBhaXJzLiJ9CmFjcm9fbmlnaHRfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIGNobG9yb1t3aGljaChjaGxvcm8kQ1MuYWNyb3BoYXNlIDwxMiAmIGNobG9ybyRDUy5hY3JvcGhhc2UgPjggKSxdJGdlbmVfc3ltYm9sKSB7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19uaWdodF9jaGxvcm8gPC0gcmJpbmQoYWNyb19uaWdodF9jaGxvcm8sIHRtcF9kZikKfQoKYWNyb19uaWdodF9jaGxvcm8gPC0gYWNyb19uaWdodF9jaGxvcm9bLTEsXQoKCm90YWZfY2hsb3JvX2Fjcm9fbmlnaHQgPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gb3RhZlt3aGljaChvdGFmJHN1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaGxvcm9wbGFzdCIgJiBvdGFmJENTLmFjcm9waGFzZSA8OCAmIG90YWYkQ1MuYWNyb3BoYXNlID40KSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG90YWZfY2hsb3JvX2Fjcm9fbmlnaHQgPC0gcmJpbmQob3RhZl9jaGxvcm9fYWNyb19uaWdodCwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX25pZ2h0IDwtIG90YWZfY2hsb3JvX2Fjcm9fbmlnaHRbLTEsXQoKCiMgUGxvdHMgCgpnZ3Bsb3QoZGF0YSA9IG90YWZfY2hsb3JvX2Fjcm9fbmlnaHQsIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMykgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZW5kIG9mIG5pZ2h0IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgoKZ2dwbG90KGRhdGEgPSBhY3JvX25pZ2h0X2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIHlsaW0oMTIsIDIxKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBtUk5BLCBhY3JvcGhhc2UgYXQgZGF3biIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgpgYGAKCkhlcmUsIHdlIGNhbiBpZGVudGlmeSBhIGtub3duIE9UQUYvY2hsb3JvcGxhc3QgbVJOQSBwYWlyOiBNUkwxIGFuZCBfcmJjTF8KCkFuZCBvdGhlciBwb3RlbnRpYWwgT1RBRi9tUk5BIHBhaXJzLi4uPwoKCmBgYHtyIE9UQUZfbVJOQV9wYWlyc19taXRvLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD04LCBmaWcuY2FwPSJDYW5kaWRhdGUgT1RBRi9tUk5BIHRhcmdldCBwYWlycy4ifQphY3JvX21pdG8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gbWl0byRnZW5lX3N5bWJvbCkgewogICAgbWl0b1ttaXRvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19taXRvIDwtIHJiaW5kKGFjcm9fbWl0bywgdG1wX2RmKQp9CgphY3JvX21pdG8gPC0gYWNyb19taXRvWy0xLF0KCgpvdGFmX21pdG9fYWNybyA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBvdGFmW3doaWNoKG90YWYkc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk1pdG9jaG9uZHJpb24iKSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG90YWZfbWl0b19hY3JvIDwtIHJiaW5kKG90YWZfbWl0b19hY3JvLCB0bXBfZGYpCn0KCm90YWZfbWl0b19hY3JvIDwtIG90YWZfbWl0b19hY3JvWy0xLF0KCgojIFBsb3RzIAoKZ2dwbG90KGRhdGEgPSBvdGFmX21pdG9fYWNybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImdvbGQiLCB4bWluID0gMTEsIHhtYXggPSAyMywgeW1pbiA9NCwgeW1heCA9IDEzLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykrCiAgICBmYWNldF93cmFwKH5nZW5lKSArCiAgICB5bGltKDQsIDEzKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9Ik1pdG9jaG9uZHJpb24gbG9jYXRlZCBPVEFGcywiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCgpnZ3Bsb3QoZGF0YSA9IGFjcm9fbWl0bywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIHlsaW0oMTEsIDE2KSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0xMSwgeW1heCA9IDE2LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMSwgeW1heCA9IDE2LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTExLCB5bWF4ID0gMTYsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJNaXRvY2hvbmRyaW9uIG1STkEiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKYGBgCgoKYGBge3IgTkNMX2V4cHJlc3Npb24sIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTgsIGZpZy5jYXA9IlJoeXRobWljIE5DTCBtUk5BIGV4cHJlc3Npb24uIn0KbmNsX2RmIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWYkZ2VuZV9zeW1ib2wpewogICAgaWYgKHN0YXJ0c1dpdGgocHJvdCwgIk5DTCIpIHwgc3RhcnRzV2l0aChwcm90LCAiTkNDIikgKXsKICAgICAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgICAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgICAgICBuY2xfZGYgPC0gcmJpbmQobmNsX2RmLCB0bXBfZGYpCiAgICB9CiAgICAKfQoKbmNsX2RmIDwtIG5jbF9kZlstMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gbmNsX2RmLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9MywgeW1heCA9IDksIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTMsIHltYXggPSA5LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTMsIHltYXggPSA5LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIHlsaW0oMywgOSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJBbGwgcmh5dGhtaWMgTkNMIGV4cHJlc3Npb24iLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKYGBgCgoKCiMjIFJlZmVyZW5jZXMKCkViZXJoYXJkIFMsIExvaXNlbGF5IEMsIERyYXBpZXIgRCwgQnVqYWxkb24gUywgR2lyYXJkLUJhc2NvdSBKLCBLdXJhcyBSLCBDaG9xdWV0IFksIFdvbGxtYW4gRkEuIER1YWwgZnVuY3Rpb25zIG9mIHRoZSBudWNsZXVzLWVuY29kZWQgZmFjdG9yIFREQTEgaW4gdHJhcHBpbmcgYW5kIHRyYW5zbGF0aW9uIGFjdGl2YXRpb24gb2YgYXRwQSB0cmFuc2NyaXB0cyBpbiBfQ2hsYW15ZG9tb25hcyByZWluaGFyZHRpaV8gY2hsb3JvcGxhc3RzLiBfUGxhbnQgSi5fIDIwMTEgU2VwOzY3KDYpOjEwNTUtNjYuIGRvaTogMTAuMTExMS9qLjEzNjUtMzEzWC4yMDExLjA0NjU3LnguIEVwdWIgMjAxMSBKdWwgMTguIFBNSUQ6IDIxNjIzOTczLgoKV2FuZyBGLCBKb2huc29uIFgsIENhdmFpdW9sbyBNLCBCb2huZSBBViwgTmlja2Vsc2VuIEosIFZhbGxvbiBPLiBUd28gX0NobGFteWRvbW9uYXNfIE9QUiBwcm90ZWlucyBzdGFiaWxpemUgY2hsb3JvcGxhc3QgbVJOQXMgZW5jb2Rpbmcgc21hbGwgc3VidW5pdHMgb2YgcGhvdG9zeXN0ZW0gSUkgYW5kIGN5dG9jaHJvbWUgYjYgZi4gX1BsYW50IEouXyAyMDE1IEp1bjs4Mig1KTo4NjEtNzMuIGRvaTogMTAuMTExMS90cGouMTI4NTguIFBNSUQ6IDI1ODk4OTgyLgoKQ2xpbmUsIFMuIEcuLCBMYXVnaGJhdW0sIEkuIEEuIGFuZCBIYW1lbCwgUC4gUC4gKDIwMTcpIENDUzIsIGFuIE9jdGF0cmljb3BlcHRpZGUtUmVwZWF0IFByb3RlaW4sIElzIFJlcXVpcmVkIGZvciBQbGFzdGlkIEN5dG9jaHJvbWUgYyBBc3NlbWJseSBpbiB0aGUgR3JlZW4gQWxnYSBfQ2hsYW15ZG9tb25hcyByZWluaGFyZHRpaV8uIF9Gcm9udGllcnMgaW4gcGxhbnQgc2NpZW5jZV8sIDgsIDEzMDYuIGh0dHBzOi8vZG9pLm9yZy8xMC4zMzg5L2ZwbHMuMjAxNy4wMTMwNgoKVmlvbGEgUywgQ2F2YWl1b2xvIE0sIERyYXBpZXIgRCwgZXQgYWwuIE1EQTEsIGEgbnVjbGV1cy1lbmNvZGVkIGZhY3RvciBpbnZvbHZlZCBpbiB0aGUgc3RhYmlsaXphdGlvbiBhbmQgcHJvY2Vzc2luZyBvZiB0aGUgX2F0cEFfIHRyYW5zY3JpcHQgaW4gdGhlIGNobG9yb3BsYXN0IG9mIF9DaGxhbXlkb21vbmFzXy4gX1RoZSBQbGFudCBKb3VybmFsOiBmb3IgQ2VsbCBhbmQgTW9sZWN1bGFyIEJpb2xvZ3lfLiAyMDE5IEp1bjs5OCg2KToxMDMzLTEwNDcuIERPSTogMTAuMTExMS90cGouMTQzMDAuCgpTaGluLUljaGlybyBPemF3YSwgTWFyaW5hIENhdmFpdW9sbywgRG9taXRpbGxlIEphcnJpZ2UsIFJpY2hhcmQgS3VyYXMsIE1hcmsgUnV0Z2VycywgU3RlcGhhbiBFYmVyaGFyZCwgRG9taW5pcXVlIERyYXBpZXIsIEZyYW5jaXMtQW5kcsOpIFdvbGxtYW4sIFl2ZXMgQ2hvcXVldCwgVGhlIE9QUiBQcm90ZWluIE1USEkxIENvbnRyb2xzIHRoZSBFeHByZXNzaW9uIG9mIFR3byBEaWZmZXJlbnQgU3VidW5pdHMgb2YgQVRQIFN5bnRoYXNlIENGbyBpbiBfQ2hsYW15ZG9tb25hcyByZWluaGFyZHRpaV8sIF9UaGUgUGxhbnQgQ2VsbF8sIFZvbHVtZSAzMiwgSXNzdWUgNCwgQXByaWwgMjAyMCwgUGFnZXMgMTE3OeKAkzEyMDMsIGh0dHBzOi8vZG9pLm9yZy8xMC4xMTA1L3RwYy4xOS4wMDc3MAoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgo=